package main

import (
	"fmt"
	"github.com/go-redis/redis"
	"time"
)

var rdb *redis.Client

func initClient() (err error) {
	rdb = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,   //use default db
		PoolSize: 100, //连接池大小
	})

	//ctx,cancel:=context.WithTimeout(context.Background(),5*time.Second)
	//defer cancel()
	_, err = rdb.Ping().Result()
	if err != nil {
		return err
	}
	return nil
}

func initClient2() (err error) {
	//连接Redis哨兵模式
	rdb := redis.NewFailoverClient(&redis.FailoverOptions{
		MasterName:    "master",
		SentinelAddrs: []string{"x.x.x.x:123456", "x.x.x.x:123456", "x.x.x.x:123456"},
	})
	_, err = rdb.Ping().Result()
	if err != nil {
		return err
	}
	return nil
}

//连接redis集群
func initClient3() (err error) {
	rdb := redis.NewClusterClient(&redis.ClusterOptions{
		Addrs: []string{":7000", ":7001", ":7002"},
	})
	_, err = rdb.Ping().Result()
	if err != nil {
		return err
	}
	return nil
}

//set/get
func redisdemo1() {
	err := rdb.Set("score", 100, 0).Err()
	if err != nil {
		return
	}
	val, err := rdb.Get("score").Result()
	fmt.Println(val)
	val2, err := rdb.Get("name").Result()
	if err == redis.Nil {
		fmt.Println("name does not exits")
	} else if err != nil {
		fmt.Println("get name failed err")
	} else {
		fmt.Println(val2)
	}
}
func redisdemo2() {
	zsetkey := "language_rank"
	languages := []redis.Z{
		redis.Z{
			Score:  12,
			Member: "golang",
		}, {
			Score:  10,
			Member: "java",
		},
	}
	num, err := rdb.ZAdd(zsetkey, languages...).Result()
	if err != nil {
		fmt.Printf("zadd failed, err:%v\n", err)
		return
	}
	fmt.Printf("zadd %d succ.\n", num)
	newscore, err := rdb.ZIncrBy(zsetkey, 10, "golang").Result()
	if err != nil {
		fmt.Printf("zincrby failed, err:%v\n", err)
		return
	}
	fmt.Printf("Golang's score is %f now.\n", newscore)

	ret, err := rdb.ZRevRangeWithScores(zsetkey, 0, 2).Result()
	if err != nil {
		fmt.Printf("zrevrange failed, err:%v\n", err)
		return
	}
	for _, z := range ret {
		fmt.Println(z.Member, z.Score)
	}
	op := redis.ZRangeBy{
		Min:    "10",
		Max:    "21",
		Offset: 0,
		Count:  0,
	}
	ret, err = rdb.ZRangeByScoreWithScores(zsetkey, op).Result()
	if err != nil {
		fmt.Printf("zrangebyscore failed, err:%v\n", err)
		return
	}
	for _, z := range ret {
		fmt.Println(z.Member, z.Score)
	}
}
func pipelinedemo() {
	pipe := rdb.Pipeline()
	incr := pipe.Incr("pip_cnt")
	pipe.Expire("pip_cnt", time.Hour)
	_, err := pipe.Exec()
	fmt.Println(incr.Val(), err)
	//INCR pipeline_counter
	//EXPIRE pipeline_counts 3600
}
func transactiondemo() {
	pipe := rdb.TxPipeline()
	incr := pipe.Incr("txpip_cnt")
	pipe.Expire("txpip_cnt", time.Hour)
	_, err := pipe.Exec()
	fmt.Println(incr.Val(), err)
}
func watchdemp() {
	key := "watchcnt"
	//watch 来在事务提交的过程中监测某个key 如果在事务提交过程中已经被修改 则事务出错
	err := rdb.Watch(func(tx *redis.Tx) error {
		n, err := tx.Get(key).Int()
		if err != nil && err != redis.Nil {
			return err
		}
		//开启事务
		_, err = tx.Pipelined(func(pipeliner redis.Pipeliner) error {
			pipeliner.Set("watch2", 12, 0)
			time.Sleep(time.Second * 5)
			pipeliner.Set(key, n+1, 0)
			return nil
		})
		return err
	}, key)
	if err != nil {
		fmt.Println(err)
	}
}
func main() {
	initClient()
	watchdemp()
	//err:=rdb.Set("key","value",0).Err()
	//rdb.Set("key1","value1",0)
	//rdb.Set("key2","value2",0)
	//if err !=nil{
	//	panic(err)
	//}
	//val,err:=rdb.Get("key").Result()
	//if err!=nil{
	//	panic(err)
	//}
	//fmt.Println("key:",val)
	//val2,err:=rdb.Get("key2").Result()
	//if err==redis.Nil{
	//	fmt.Println("key2 dose not exist")
	//}else if err!=nil{
	//	panic(err)
	//}else{
	//	fmt.Println("key2",val2)
	//}
	////根据前缀获取Key
	//vals,err:=rdb.Keys("ke*").Result()
	//
	//fmt.Printf("%#v\n",vals)
	////执行自定义命令
	//res,err:=rdb.Do("set", "key3"," values").Result()
	//fmt.Println(res)
	////按通配符删除key

}
